﻿using Sustainalytics.Accounts.Service.Auth;
using Sustainalytics.Accounts.Service.Models;
using Sustainalytics.Auth.Claims;
using Sustainalytics.DataLayer;
using Sustainalytics.Utils;
using System;
using System.Collections.Generic;
using System.Configuration;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Security.Claims;
using System.Web.Http;
using System.Web.Http.Cors;

namespace Sustainalytics.Accounts.Service.Controllers
{
    [EnableCors(origins: "*", headers: "*", methods: "*")]
    public class AccountController : ApiController
    {
        private readonly IAuthProvider _authProvider;

        public AccountController(IAuthProvider authProvider)
        {
            _authProvider = authProvider;
        }

        [HttpPost]
        [Route("api/account/profile")]
        public UserInfo Profile()
        {
            var principal = Request.GetRequestContext().Principal as ClaimsPrincipal;

            if (principal == null)
            {
                return new UserInfo();
            }
            return GetUserInfoForGaUser(principal);
        }

        [HttpPost]
        [Route("api/account/forgotPassword")]
        public HttpResponseMessage ForgotPassword([FromBody]string username)
        {
            return ExcecuteAuthProviderAction(
                authProvider => authProvider.ForgotPassword(username.ToLowerInvariant()));
        }

        [HttpPost]
        [Route("api/account/changePassword")]
        public HttpResponseMessage ChangePassword([FromBody]ChangePasswordModel changePassword)
        {
            return ExcecuteAuthProviderAction(
                authProvider => authProvider.ChangePassword(changePassword.Username, changePassword.OldPassword, changePassword.NewPassword));
        }

        [HttpPost]
        [Route("api/account/setPassword")]
        public HttpResponseMessage SetPassword([FromBody]SetPasswordModel changePassword)
        {
            return ExcecuteAuthProviderAction(
                authProvider => authProvider.SetPassword(changePassword.Username, changePassword.Password));
        }

        [HttpPost]
        [Route("api/account/acceptLegalAgreement")]
        public HttpResponseMessage AcceptLegalAgreement([FromBody]string username)
        {
            return ExcecuteAuthProviderAction(
                authProvider => authProvider.AcceptLegalAgreement(username.ToLowerInvariant()));
        }

        [HttpPost]
        [Route("api/account/acceptFirstTimeRRUser")]
        public HttpResponseMessage AcceptFirstTimeRRUser([FromBody]string username)
        {
            return ExcecuteAuthProviderAction(
                authProvider => authProvider.AcceptFirstTimeRRUser(username.ToLowerInvariant()));
        }

        [HttpPost]
        [Route("api/account/acceptFirstTimeSPUser")]
        public HttpResponseMessage AcceptFirstTimeSPUser([FromBody]string username)
        {
            return ExcecuteAuthProviderAction(
                authProvider => authProvider.AcceptFirstTimeSPUser(username.ToLowerInvariant()));
        }

        private static UserInfo GetUserInfoForGaUser(ClaimsPrincipal principal)
        {
            var userInfo = GetBasicUserInfo(principal);
            userInfo.UserId = principal.Claims.First(c => c.Type == CustomClaimTypes.UserId).Value;
            userInfo.Account = principal.Claims.First(c => c.Type == CustomClaimTypes.AccountName).Value;
            userInfo.AccountId = principal.Claims.First(c => c.Type == CustomClaimTypes.AccountId).Value;
            userInfo.AccountTier = Convert.ToInt32(principal.Claims.First(c => c.Type == CustomClaimTypes.AccountTier).Value);
            userInfo.AccountManagerEmail = principal.Claims.First(c => c.Type == CustomClaimTypes.AccountManagerEmail).Value;
            userInfo.EsgProfileId = principal.Claims.First(c => c.Type == CustomClaimTypes.EsgProfileId).Value;
            userInfo.FirstTimeRRUserAccepted = Convert.ToBoolean(principal.Claims.First(c => c.Type == "first_user_RR").Value);
            userInfo.FirstTimeSPUserAccepted = Convert.ToBoolean(principal.Claims.First(c => c.Type == "first_user_SP").Value);
            return userInfo;
        }

        private static UserInfo GetBasicUserInfo(ClaimsPrincipal principal)
        {
            return new UserInfo
            {
                Name = principal.Identity.Name,
                IsAuthenticated = principal.Identity.IsAuthenticated,
                Email = principal.Claims.First(c => c.Type == ClaimTypes.Email).Value,
                Username = principal.Claims.First(c => c.Type == ClaimTypes.Name).Value,
                FirstName = principal.Claims.First(c => c.Type == ClaimTypes.GivenName).Value.Split(' ')[0],
                LastName = principal.Claims.First(c => c.Type == ClaimTypes.Surname).Value
            };
        }

        private HttpResponseMessage ExcecuteAuthProviderAction(Action<IAuthProvider> action)
        {
            try
            {
                action.Invoke(_authProvider);

                return Request.CreateResponse(HttpStatusCode.OK);
            }
            catch (CustomException ex)
            {
                if (ex.InternalCode != null)
                {
                    return Request.CreateResponse(HttpStatusCode.InternalServerError, new ErrorDto { Code = (int)ex.InternalCode });
                }

                return Request.CreateResponse(HttpStatusCode.InternalServerError, ex.Message);
            }
        }
    }
}
